# analysis/evaluation.py

def precision_recall_fscore(detected_community, known_community):
    """
    计算社区检测结果的 PRF 指标。
    :param detected_community: 检测到的社区节点列表
    :param known_community: 已知社区节点列表
    :return: (recall, precision, f_score, jaccard)
    """
    detected_set = set(detected_community)
    known_set = set(known_community)

    intersect = detected_set & known_set
    union = detected_set | known_set

    recall = len(intersect) / len(known_set) if known_set else 0
    precision = len(intersect) / len(detected_set) if detected_set else 0
    f_score = 2 * (precision * recall) / (precision + recall + 1e-9)
    jaccard = len(intersect) / len(union) if union else 0

    return recall, precision, f_score, jaccard


def compare_multiple_communities(detected_communities, known_communities):
    """
    比较多个检测社区与已知社区之间的平均 PRF。
    :param detected_communities: List[List[int]] 检测到的社区列表
    :param known_communities: List[List[int]] 已知社区列表
    :return: 平均指标
    """
    total_r, total_p, total_f, total_j = [], [], [], []

    for i, detected in enumerate(detected_communities):
        for j, known in enumerate(known_communities):
            r, p, f, j = precision_recall_fscore(detected, known)
            total_r.append(r)
            total_p.append(p)
            total_f.append(f)
            total_j.append(j)

    avg_r = sum(total_r) / len(total_r) if total_r else 0
    avg_p = sum(total_p) / len(total_p) if total_p else 0
    avg_f = sum(total_f) / len(total_f) if total_f else 0
    avg_j = sum(total_j) / len(total_j) if total_j else 0

    return {
        "avg_recall": avg_r,
        "avg_precision": p,
        "avg_f_score": f,
        "avg_jaccard": j
    }


if __name__ == "__main__":
    detected = [813, 1234, 967]
    known = [813, 1234, 967, 1001]

    r, p, f, j = precision_recall_fscore(detected, known)
    print(f"Recall: {r:.4f}, Precision: {p:.4f}, F1: {f:.4f}, Jaccard: {j:.4f}")
